home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / utils / unix / unzip-5.12 / extract.c < prev    next >
C/C++ Source or Header  |  1994-08-15  |  47KB  |  1,134 lines

  1. /*---------------------------------------------------------------------------
  2.  
  3.   extract.c
  4.  
  5.   This file contains the high-level routines ("driver routines") for extrac-
  6.   ting and testing zipfile members.  It calls the low-level routines in files
  7.   explode.c, inflate.c, unreduce.c and unshrink.c.
  8.  
  9.   ---------------------------------------------------------------------------*/
  10.  
  11.  
  12. #include "unzip.h"
  13. #include "crypt.h"
  14. #ifdef MSWIN
  15. #  include "wizunzip.h"
  16. #  include "replace.h"
  17. #endif
  18.  
  19. int newfile;      /* used also in file_io.c (flush()) */
  20. ulg *crc_32_tab;  /* used also in file_io.c and crypt.c (full version) */
  21.  
  22. static void makecrc __((void));
  23. static int store_info __((void));
  24. static int extract_or_test_member __((void));
  25.  
  26.  
  27. /*******************************/
  28. /*  Strings used in extract.c  */
  29. /*******************************/
  30.  
  31. static char Far VersionMsg[] =
  32.   "   skipping: %-22s  need %s compat. v%u.%u (can do v%u.%u)\n";
  33. static char Far ComprMsg[] =
  34.   "   skipping: %-22s  compression method %d\n";
  35. static char Far FilNamMsg[] =
  36.   "%s:  bad filename length (%s)\n";
  37. static char Far ExtFieldMsg[] =
  38.   "%s:  bad extra field length (%s)\n";
  39. static char Far OffsetMsg[] =
  40.   "file #%d:  bad zipfile offset (%s):  %ld\n";
  41. static char Far ExtractMsg[] =
  42.   "%8sing: %-22s  %s%s";
  43. #ifndef SFX
  44.    static char Far LengthMsg[] =
  45.      "%s  %s:  %ld bytes required to uncompress to %lu bytes;\n    %s\
  46.       supposed to require %lu bytes%s%s%s\n";
  47. #endif
  48.  
  49. static char Far BadFileCommLength[] = "\n%s:  bad file comment length\n";
  50. static char Far LocalHdrSig[] = "local header sig";
  51. static char Far BadLocalHdr[] = "\nfile #%d:  bad local header\n";
  52. static char Far AttemptRecompensate[] = "  (attempting to re-compensate)\n";
  53. static char Far SkipVolumeLabel[] = "   skipping: %-22s  %svolume label\n";
  54. static char Far ReplaceQuery[] =
  55.   "replace %s? [y]es, [n]o, [A]ll, [N]one, [r]ename: ";
  56. static char Far AssumeNone[] = " NULL\n(assuming [N]one)\n";
  57. static char Far NewName[] = "new name: ";
  58. static char Far InvalidResponse[] = "error:  invalid response [%c]\n";
  59. static char Far ErrorInArchive[] = "At least one %serror was detected in %s.\n";
  60. static char Far ZeroFilesTested[] = "Caution:  zero files tested in %s.\n";
  61.  
  62. #ifndef VMS
  63.    static char Far VMSFormat[] =
  64.      "\n%s:  stored in VMS format.  Extract anyway? (y/n) ";
  65. #endif
  66.  
  67. #ifdef CRYPT
  68.    static char Far SkipCantGetPasswd[] =
  69.      "   skipping: %-22s  unable to get password\n";
  70.    static char Far SkipIncorrectPasswd[] =
  71.      "   skipping: %-22s  incorrect password\n";
  72.    static char Far FilesSkipBadPasswd[] =
  73.      "%d file%s skipped because of incorrect password.\n";
  74.    static char Far MaybeBadPasswd[] =
  75.      "    (may instead be incorrect password)\n";
  76. #else
  77.    static char Far SkipEncrypted[] =
  78.      "   skipping: %-22s  encrypted (not supported)\n";
  79. #endif
  80.  
  81. static char Far NoErrInCompData[] =
  82.   "No errors detected in compressed data of %s.\n";
  83. static char Far NoErrInTestedFiles[] =
  84.   "No errors detected in %s for the %d file%s tested.\n";
  85. static char Far FilesSkipped[] =
  86.   "%d file%s skipped because of unsupported compression or encoding.\n";
  87.  
  88. static char Far ErrUnzipFile[] = "  error:  %s%s %s\n";
  89. static char Far ErrUnzipNoFile[] = "\n  error:  %s%s\n";
  90. static char Far NotEnoughMem[] = "not enough memory to ";
  91. static char Far InvalidComprData[] = "invalid compressed data to ";
  92. static char Far Inflate[] = "inflate";
  93.  
  94. #ifndef SFX
  95.    static char Far Explode[] = "explode";
  96.    static char Far Unshrink[] = "unshrink";
  97. #endif
  98.  
  99. static char Far FileUnknownCompMethod[] = "%s:  unknown compression method\n";
  100. static char Far BadCRC[] = " bad CRC %08lx  (should be %08lx)\n";
  101. static char Far UnsupportedExtraField[] =
  102.   "warning:  unsupported extra field compression type--skipping\n";
  103. static char Far BadExtraFieldCRC[] =
  104.   "error [%s]:  bad extra field CRC %08lx (should be %08lx)\n";
  105.  
  106.  
  107.  
  108.  
  109.  
  110. /**************************************/
  111. /*  Function extract_or_test_files()  */
  112. /**************************************/
  113.  
  114. int extract_or_test_files()    /* return PK-type error code */
  115. {
  116.     uch *cd_inptr;
  117.     int cd_incnt, error, error_in_archive=PK_COOL;
  118.     int i, j, renamed, query, len, filnum=(-1), blknum=0;
  119.     int *fn_matched=NULL, *xn_matched=NULL;
  120.     ush members_remaining, num_skipped=0, num_bad_pwd=0;
  121.     long cd_bufstart, bufstart, inbuf_offset, request;
  122.     LONGINT old_extra_bytes=0L;
  123.     static min_info info[DIR_BLKSIZ];
  124.  
  125.  
  126. /*---------------------------------------------------------------------------
  127.     The basic idea of this function is as follows.  Since the central di-
  128.     rectory lies at the end of the zipfile and the member files lie at the
  129.     beginning or middle or wherever, it is not very desirable to simply
  130.     read a central directory entry, jump to the member and extract it, and
  131.     then jump back to the central directory.  In the case of a large zipfile
  132.     this would lead to a whole lot of disk-grinding, especially if each mem-
  133.     ber file is small.  Instead, we read from the central directory the per-
  134.     tinent information for a block of files, then go extract/test the whole
  135.     block.  Thus this routine contains two small(er) loops within a very
  136.     large outer loop:  the first of the small ones reads a block of files
  137.     from the central directory; the second extracts or tests each file; and
  138.     the outer one loops over blocks.  There's some file-pointer positioning
  139.     stuff in between, but that's about it.  Btw, it's because of this jump-
  140.     ing around that we can afford to be lenient if an error occurs in one of
  141.     the member files:  we should still be able to go find the other members,
  142.     since we know the offset of each from the beginning of the zipfile.
  143.   ---------------------------------------------------------------------------*/
  144.  
  145.     pInfo = info;
  146.     members_remaining = ecrec.total_entries_central_dir;
  147. #if (defined(CRYPT) || !defined(NO_ZIPINFO))
  148.     newzip = TRUE;
  149. #endif
  150.  
  151.     /* malloc space for CRC table and generate it */
  152.     if ((crc_32_tab = (ulg *)malloc(256*sizeof(ulg))) == (ulg *)NULL)
  153.         return PK_MEM2;
  154.     makecrc();
  155.  
  156.     /* malloc space for check on unmatched filespecs (OK if one or both NULL) */
  157.     if (filespecs > 0  &&
  158.         (fn_matched=(int *)malloc(filespecs*sizeof(int))) != (int *)NULL)
  159.         for (i = 0;  i < filespecs;  ++i)
  160.             fn_matched[i] = FALSE;
  161.     if (xfilespecs > 0  &&
  162.         (xn_matched=(int *)malloc(xfilespecs*sizeof(int))) != (int *)NULL)
  163.         for (i = 0;  i < xfilespecs;  ++i)
  164.             xn_matched[i] = FALSE;
  165.  
  166. /*---------------------------------------------------------------------------
  167.     Begin main loop over blocks of member files.  We know the entire central
  168.     directory is on this disk:  we would not have any of this information un-
  169.     less the end-of-central-directory record was on this disk, and we would
  170.     not have gotten to this routine unless this is also the disk on which
  171.     the central directory starts.  In practice, this had better be the ONLY
  172.     disk in the archive, but maybe someday we'll add multi-disk support.
  173.   ---------------------------------------------------------------------------*/
  174.  
  175.     while (members_remaining) {
  176.         j = 0;
  177.  
  178.         /*
  179.          * Loop through files in central directory, storing offsets, file
  180.          * attributes, case-conversion and text-conversion flags until block
  181.          * size is reached.
  182.          */
  183.  
  184.         while (members_remaining && (j < DIR_BLKSIZ)) {
  185.             --members_remaining;
  186.             pInfo = &info[j];
  187.  
  188.             if (readbuf(sig, 4) == 0) {
  189.                 error_in_archive = PK_EOF;
  190.                 members_remaining = 0;  /* ...so no more left to do */
  191.                 break;
  192.             }
  193.             if (strncmp(sig, central_hdr_sig, 4)) {  /* just to make sure */
  194.                 FPRINTF(stderr, LoadFarString(CentSigMsg), j);  /* sig not found */
  195.                 FPRINTF(stderr, LoadFarString(ReportMsg));   /* check binary transfers */
  196.                 error_in_archive = PK_BADERR;
  197.                 members_remaining = 0;  /* ...so no more left to do */
  198.                 break;
  199.             }
  200.             /* process_cdir_file_hdr() sets pInfo->hostnum, pInfo->lcflag */
  201.